package org.rhq.sample.client.java.ldap; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.authz.Role; import org.rhq.core.domain.criteria.ResourceCriteria; import org.rhq.core.domain.criteria.ResourceGroupCriteria; import org.rhq.core.domain.criteria.RoleCriteria; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.group.ResourceGroup; import org.rhq.core.domain.util.PageList; import org.rhq.enterprise.client.RemoteClient; import org.rhq.enterprise.server.auth.SubjectManagerRemote; import org.rhq.enterprise.server.authz.RoleManagerRemote; import org.rhq.enterprise.server.resource.ResourceManagerRemote; import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote; /** * This sample program utilizes the RHQ Remote API via a Java Client. * * The RHQ CLI is the preferred remote client approach for script-based clients. Programmatic Java clients * can utilize the Remote API via the same mechanism used by the CLI, making use of ClientMain object, as * done in this sample. This is the recommended mechanism although a remote Java client could als use the * remote API exposed as WebServices. * * @author Jay Shaughnessy */ public class SampleLdapClientMain { // A remote session always starts with a login, define default user/password/server/port private static String username = "rhqadmin"; private static String password = "rhqadmin"; private static String host = "localhost"; private static int port = 7080; /** * This is a standalone remote client but calls to the remote API could be embedded into another application. */ public static void main(String[] args) { if (args.length > 0) { if ((args.length != 2) && (args.length != 4)) { System.out .println("\nUsage: SampleLdapClientMain [ [ username password ] | [username password host port] ]"); System.out.println("\n\nDefault credentials: rhqadmin/rhqadmin"); System.out.println("\n\nDefault host: determined from wsconsume of WSDL"); return; } else { username = args[0]; password = args[1]; if (args.length == 4) { host = args[2]; port = Integer.valueOf(args[3]); } } } LdapClient ldapClient = null; try { ldapClient = new LdapClient(); ldapClient.synchLdapJbasManagers(); } catch (Throwable t) { System.out.println("Error: " + t); t.printStackTrace(); } finally { if (null != ldapClient) { // clean up the session by logging out from the RHQ server ldapClient.logout(); } } } /** * The LdapClient interacts with the RHQ Server to help synchronize a (fake) LDAP server with RHQ. */ public static class LdapClient { // group containing all jbas resources private static final String JBAS_GROUP = "jbas-resource-group"; // role for jbas managers private static final String JBAS_MANAGER_ROLE = "jbas-manager-role"; // the users that should be assigned the JBAS_MANAGER_ROLE private static final List<String> JBAS_MANAGERS = new ArrayList<String>(); // the prmissions that should be assigned the JBAS_MANAGER_ROLE private static final Set<Permission> JBAS_MANAGER_PERMISSIONS = new HashSet<Permission>(); // jbas AS Server resource type (note, this picks up AS4 and AS5 resources as they share the same type name) private static final String JBAS_SERVER_NAME = "JBossAS Server"; /* The Remote API offers different remote "managers" roughly broken down by subsystem/function * Below are the managers needed by this client, there are several others that offer * interfaces into areas such as operations, alerting, content, etc. See the API. */ private ResourceGroupManagerRemote resourceGroupManager; private ResourceManagerRemote resourceManager; private RoleManagerRemote roleManager; private SubjectManagerRemote subjectManager; /* This represents the RHQ user that is logged in and making the remote calls. This user must * already exist. For the work being done here the user must also have SECURITY_MANAGER permissions. */ private Subject subject; /* This is the object through which we access the remote API */ private RemoteClient remoteClient; static { // add some fake users since we're not actually hooked into an ldap server JBAS_MANAGERS.add("mgr-1"); JBAS_MANAGERS.add("mgr-2"); // add some permissions since we're not actually hooked into an ldap server JBAS_MANAGER_PERMISSIONS.addAll(Permission.RESOURCE_ALL); } public LdapClient() throws Exception { this.remoteClient = new RemoteClient(null, host, port); this.subject = remoteClient.login(username, password); this.resourceGroupManager = this.remoteClient.getResourceGroupManagerRemote(); this.resourceManager = this.remoteClient.getResourceManagerRemote(); this.roleManager = this.remoteClient.getRoleManagerRemote(); this.subjectManager = this.remoteClient.getSubjectManagerRemote(); } /* * This method simulates a synch between an Ldap server that has defined a group of JBAS managers * and wants to associate them with a role allowing jbas management. Meaning, a role that * has the proper permissions and is associated with the jbas resources. */ private void synchLdapJbasManagers() throws Exception { // create the jbas manager role if necessary // use a criteria search with a name filter to look for the role RoleCriteria roleCriteria = new RoleCriteria(); roleCriteria.setFilterName(JBAS_MANAGER_ROLE); PageList<Role> jbasManagerRoles = roleManager.findRolesByCriteria(subject, roleCriteria); Role jbasManagerRole; if (1 == jbasManagerRoles.size()) { jbasManagerRole = jbasManagerRoles.get(0); } else { // if it doesn't exist, create it jbasManagerRole = new Role(JBAS_MANAGER_ROLE); jbasManagerRole = roleManager.createRole(subject, jbasManagerRole); } // ensure the proper permissions are granted to the role by using an update jbasManagerRole.setPermissions(JBAS_MANAGER_PERMISSIONS); roleManager.updateRole(subject, jbasManagerRole); // create, populate and associate the jbas group if necessary ResourceGroupCriteria resourceGroupCriteria = new ResourceGroupCriteria(); resourceGroupCriteria.addFilterName(JBAS_GROUP); PageList<ResourceGroup> jbasGroups = resourceGroupManager.findResourceGroupsByCriteria(subject, resourceGroupCriteria); ResourceGroup jbasGroup; if (1 == jbasGroups.size()) { jbasGroup = jbasGroups.get(0); } else { jbasGroup = new ResourceGroup(JBAS_GROUP); jbasGroup = resourceGroupManager.createResourceGroup(subject, jbasGroup); // Ensure the group is recursive to make all the children available. // In this case a specific method is available, so a general update call is not needed. resourceGroupManager.setRecursive(subject, jbasGroup.getId(), true); } // Now find all of the JBAS server resources by adding a criteria filter on resource type name ResourceCriteria resourceCriteria = new ResourceCriteria(); resourceCriteria.addFilterResourceTypeName(JBAS_SERVER_NAME); PageList<Resource> jbasServers = resourceManager.findResourcesByCriteria(subject, resourceCriteria); if (!jbasServers.isEmpty()) { int[] jbasServerIds = new int[jbasServers.size()]; int i = 0; for (Resource jbasServer : jbasServers) { jbasServerIds[i++] = jbasServer.getId(); } // ..and add them to the group which will be associated with the manager role resourceGroupManager.addResourcesToGroup(subject, jbasGroup.getId(), jbasServerIds); } // Now, associate the mixed group of Jbas servers to the manager role roleManager.addResourceGroupsToRole(subject, jbasManagerRole.getId(), new int[] { jbasGroup.getId() }); // synch managers with the role // 1. remove obsolete managers roleCriteria = new RoleCriteria(); roleCriteria.setFilterId(jbasManagerRole.getId()); // add a fetch criteria to the criteria object to get the optionally returned subjects for the role. roleCriteria.setFetchSubjects(true); jbasManagerRole = roleManager.findRolesByCriteria(subject, roleCriteria).get(0); Set<Subject> subjects = jbasManagerRole.getSubjects(); if ((null != subjects) && !subjects.isEmpty()) { for (Subject subject : subjects) { if (!JBAS_MANAGERS.contains(subject.getName())) { roleManager.removeSubjectsFromRole(subject, jbasManagerRole.getId(), new int[] { subject .getId() }); } } } // 2. add new managers, create subjects for the managers, if necessary Subject jbasManagerSubject; for (String jbasManager : JBAS_MANAGERS) { jbasManagerSubject = subjectManager.getSubjectByName(jbasManager); // add the required fields for a subject, note that we skip credentials since this is // simulating ldap if (null == jbasManagerSubject) { jbasManagerSubject = new Subject(); jbasManagerSubject.setName(jbasManager); jbasManagerSubject.setEmailAddress("jbas.manager@sample.com"); jbasManagerSubject.setFactive(true); jbasManagerSubject.setFsystem(false); jbasManagerSubject = subjectManager.createSubject(subject, jbasManagerSubject); } // Finally, make sure my current set of jbas managers is associated with the manager role. roleManager.addSubjectsToRole(subject, jbasManagerRole.getId(), new int[] { jbasManagerSubject.getId() }); } } public void logout() { if ((null != subjectManager) && (null != subject)) { try { subjectManager.logout(subject); } catch (Exception e) { // just suppress the exception, nothing else we can do } } } } }